/******************************************************************************************************
Copyright (C) 2008 Mestrelab Research S.L. All rights reserved.

This file is part of the MNova scripting toolkit.

Authorized users of MNova Software may use this file freely, but this file is provided AS IS
with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE.
*****************************************************************************************************/
/*jslint plusplus: true, nomen: true, indent: 4, white: true*/
/*global Molecule, molecule, nmr, MoleculePlugin, Application, Atom, NMRAssignments*/

function assignmentTest()
{
	"use strict";
	var atomNumber = 6,
		h = 1,
		moleculePlugin = new MoleculePlugin(Application.molecule),
		mol, atom, assign, shift;
	
	if( moleculePlugin === undefined) {
		return;
	}
	
	mol = new Molecule(moleculePlugin.activeMolecule());
	if( mol.isValid() === false ) {
		throw "Invalid Molecule";
	}
	
	atom = new Atom(mol.atom(atomNumber));
	print(atom.text);
	assign = new NMRAssignments(mol);
	print(assign);
	shift = assign.chemShift(atomNumber, h);
	if( shift !== undefined ) {
		print(JSON.stringify(shift, null, 2));
	}

	//assign to single value
	assign.setChemShift(6, 0, 13.5);
	//assign to range
	assign.setChemShift(6, 1, 1.0, 2.0);
	//assing to range with value
	assign.setChemShift(3, 1, 1.25, 2, 1.30);
	//assing with two objects
	assign.setChemShift( {"index": 11, "h": "a"},
						 {"shift": 1.9, "min": 1.85, "max": 1.92 } );
	//assing with one object
	assign.setChemShift({
		"atom": {"index": 21, "h": "b"},
		"shift": [2.6, 2.65] //this assigns to a list of values
	});
}

function assignedMoleculeTest() {
	'use strict';
	var mol = new Molecule(Application.molecule.activeMolecule()),
		assignments;

	if (!mol.isValid()) {
		throw "Invalid Molecule";
	}

	assignments = mol.nmrAssignments();
	print(JSON.stringify(assignments, null, 2));
}

function setAssignmentsTest() {
	'use strict';

	var mol = new Molecule(Application.molecule.activeMolecule()),
		assignments;

	if (!mol.isValid()) {
		throw "Invalid Molecule";
	}

	assignments = [
		{atom: {index: 3}, shift: [13, 14]},
		{atom: {index: 4, h:'a'}, shift: [{min: 7.21, max: 7.25}]},
		{atom: {index: 6, h: 'a'}, shift: [7.95]},
		{atom: {index: 7, h: 'a'}, shift: [{min: 1.20, max: 1.25, shift: 1.21},
										   {min: 2, max: 2.5, shift: 2.45}]}
	];
	mol.setNMRAssignments(assignments, true); //the second parameter clears all previous assignments

	var assigns = new NMRAssignments(mol);
	assigns.setChemShift(10, 1, 7.215, 7.255);
	assigns.setChemShift(11, 2, 5, 5.5, 5.12);
}

function jsTest() {
	'use strict';

	var mol = new Molecule(Application.molecule.activeMolecule()),
		assignments = mol.nmrAssignments(),
		nmrAssignsObj = new NMRAssignments(mol);

	if (!mol.isValid()) {
		throw "Invalid Molecule";
	}

	print(JSON.stringify(assignments, null, 2));

	print(JSON.stringify(nmrAssignsObj.jConsts(4, 1)));
	print(JSON.stringify(nmrAssignsObj.ambigJs(9, 1)));

	nmrAssignsObj.setJConsts(11, 1, [{"atom":{"h":"a","index":13},"value":5}]);
	print(JSON.stringify(mol.nmrAssignments(), null, 2));
}

function filteredNMRAssignments() {
	"use strict";

	var mol = molecule.activeMolecule(),
		molAssignments = mol.nmrAssignments(), //this returns an array with all assignments
		nmrSpc = nmr.activeSpectrum(),
		peaks = nmrSpc.peaks(),
		multiplets = nmrSpc.multiplets(),
		integrals = nmrSpc.integrals(),
		peakAssignments, assignPeaks;

	print("Peaks size {0}".format(peaks.count));
	print("Integrals size {0}".format(integrals.count));
	print("Multiplets size {0}".format(multiplets.count));

	//returns a filtered hard-copy
	function getByShiftFilter(aAssignments, aFilterFunc) {
		var assignments;

		assignments = aAssignments.map(function (aAtomAssignment) {
			//deep copy
			var newVal = JSON.parse(JSON.stringify(aAtomAssignment));
			newVal.shift = newVal.shift.filter(aFilterFunc);
			return newVal;
		});

		return assignments.filter(function (aAtomAssignment) {
			return aAtomAssignment.shift.length;
		});
	}

	//returns an array with the assignments of a specific type
	function getByShiftType(aAssignments, aType) {
		return getByShiftFilter(aAssignments, function (aShiftValue) {
			return aShiftValue.type === aType;
		});
	}

	//returns an array with the assignments to an specific UUID (peak, multiplet, integral)
	function getByShiftUUID(aAssignments, aUUID) {
		return getByShiftFilter(aAssignments, function (aShiftValue) {
			return aShiftValue.uuid === aUUID;
		});
	}

	//returns a filtered hard-copy
	function getByAtomFilter(aAssignments, aFilterFunc) {
		var assignments;
		assignments = aAssignments.filter(aFilterFunc);

		//return a deep copy of the object
		return assignments.map(function (aAtomAssignment) {
			return JSON.parse(JSON.stringify(aAtomAssignment));
		});
	}

	//returns an array with the assignments to an specific element
	function getByElement(aAssignments, aElem) {
		return getByAtomFilter(aAssignments, function (aAtomAssignment) {
			return aAtomAssignment.element === aElem;
		});
	}

	//returns an array with the assignements to an specific atom number
	function getByAtomIndex(aAssignments, aAtomIndex) {
		return getByAtomFilter(aAssignments, function (aAtomAssignment) {
			return aAtomAssignment.atom.index === aAtomIndex;
		});
	}

	//Filter the list of assignments by type. getByShiftType returns a deep copy!
	print("By Peak:");
	peakAssignments = getByShiftType(molAssignments, "Peak");
	print(JSON.stringify(peakAssignments, null, 2));
	print("By Multiplet:");
	print(JSON.stringify(getByShiftType(molAssignments, "Multiplet"), null, 2));
	print("By Integral:");
	print(JSON.stringify(getByShiftType(molAssignments, "Integral"), null, 2));

	//Filter the list of assignments by UUID
	print("By UUID {20c222a1-d47c-442d-a60c-716fe825df61}"); //it's a UUID the type does not matter
	print(JSON.stringify(
		getByShiftUUID(
			molAssignments,
			"{20c222a1-d47c-442d-a60c-716fe825df61}"), null, 2));

	//Filter the list of assignments by element symbol
	print("By Element H:");
	print(JSON.stringify(getByElement(molAssignments, "H"), null, 2));
	print("By Element C:");
	print(JSON.stringify(getByElement(molAssignments, "C"), null, 2));

	//Filter by atom number
	print("By Atom Index 14");
	print(JSON.stringify(getByAtomIndex(molAssignments, 14), null, 2));

	//get assigned peaks
	function shiftToPeakList(aAtomAssignment) {
		return aAtomAssignment.shift.reduce(
			function (aTotal, aCurrentVal) {
				aTotal.push(peaks.byId(aCurrentVal.uuid));
				return aTotal;
			}, []);
	}

    if (peakAssignments.length) {
        assignPeaks = shiftToPeakList(peakAssignments[0]);
        assignPeaks.forEach(function (aPeak) {
            print("Shift: {0}. Intensity: {1}".format(
                      aPeak.delta(1), aPeak.intensity));
        });
    }
}
